
package com.joysuch.wwyt.core.service.impl;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.joysuch.wwyt.bp.entity.BpJob;
import com.joysuch.wwyt.bp.repository.BpJobDao;
import com.joysuch.wwyt.config.RedisClient;
import com.joysuch.wwyt.core.bean.AuthorityBean;
import com.joysuch.wwyt.core.bean.AuthorityOperationBean;
import com.joysuch.wwyt.core.bean.BaseMenuFunctionEditBean;
import com.joysuch.wwyt.core.bean.BaseRoleAddUserBean;
import com.joysuch.wwyt.core.bean.BaseRoleUserListBean;
import com.joysuch.wwyt.core.bean.BaseUserRoleListSearchBean;
import com.joysuch.wwyt.core.bean.DashboardMenuBean;
import com.joysuch.wwyt.core.bean.DashboardMenuDetailBean;
import com.joysuch.wwyt.core.bean.SimpleSelectListBean;
import com.joysuch.wwyt.core.bean.UserAssignRoleBean;
import com.joysuch.wwyt.core.common.ajax.ResultBean;
import com.joysuch.wwyt.core.constant.Constants;
import com.joysuch.wwyt.core.entity.BaseMenuFunction;
import com.joysuch.wwyt.core.entity.BaseRole;
import com.joysuch.wwyt.core.entity.BaseRoleMenuFunction;
import com.joysuch.wwyt.core.entity.BaseRoleUserLoginRole;
import com.joysuch.wwyt.core.entity.BaseUser;
import com.joysuch.wwyt.core.entity.BaseUserMenuFunction;
import com.joysuch.wwyt.core.entity.dsl.QBaseMenuFunction;
import com.joysuch.wwyt.core.enums.MenuTypes;
import com.joysuch.wwyt.core.mapper.BaseUserMapper;
import com.joysuch.wwyt.core.repository.BaseMenuFunctionDao;
import com.joysuch.wwyt.core.repository.BaseRoleDao;
import com.joysuch.wwyt.core.repository.BaseRoleMenuFunctionDao;
import com.joysuch.wwyt.core.repository.BaseRoleUserLoginRoleDao;
import com.joysuch.wwyt.core.repository.BaseUserDao;
import com.joysuch.wwyt.core.repository.BaseUserMenuFunctionDao;
import com.joysuch.wwyt.core.security.ShiroUser;
import com.joysuch.wwyt.core.service.AuthorityService;
import com.joysuch.wwyt.core.support.Context;
import com.joysuch.wwyt.licence.service.LicenceService;
import com.querydsl.core.types.Predicate;
import javafx.util.Pair;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.session.Session;
import org.apache.shiro.session.mgt.DefaultSessionManager;
import org.apache.shiro.session.mgt.eis.SessionDAO;
import org.apache.shiro.util.Assert;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

@Slf4j
@Service
public class AuthorityServiceImpl implements AuthorityService {

    @Autowired
    private BpJobDao jobDao;
    @Autowired
    private BaseUserDao userDao;
    @Autowired
    private BaseRoleDao roleDao;
    @Autowired
    private BaseUserMenuFunctionDao userMenuFunctionDao;
    @Autowired
    private BaseMenuFunctionDao menuFunctionDao;
    @Autowired
    private BaseRoleMenuFunctionDao roleMenuFunctionDao;

    @Autowired
    private BaseRoleUserLoginRoleDao baseRoleUserLoginRoleDao;

    @Autowired
    private DefaultSessionManager defaultSessionManager;
    @Autowired
    private BaseUserMapper baseUserMapper;
    @Autowired
    private RedisClient redisClient;

    @Autowired
    private LicenceService licenceService;

    /**
     * 解析并组装前端菜单树结构
     *
     * @param functions 用户授权菜单集合
     * @return
     */
    @Override
    public List<AuthorityBean> parse(Collection<BaseMenuFunction> functions) {
        Map<Long, AuthorityBean> beanIdMap = new HashMap<>();
        List<AuthorityBean> top = new ArrayList<>(4);
        for (BaseMenuFunction m : functions) {
            try {
                if (m.isFolder() || m.isMenu()) {
                    AuthorityBean bean = beanIdMap.get(m.getId());
                    if (bean == null) {
                        bean = convert2Menu(m, top);
                        beanIdMap.put(m.getId(), bean);
                    }
                    AuthorityBean parent = createPath(getSafeParent(m), beanIdMap, top);
                    if (parent != null) {
                        parent.addChild(bean);
                        // 去除子类的前缀
                        bean.setName(bean.getUrl());
                        if (bean.getUrl() != null && parent.getUrl() != null) {
                            bean.setName(bean.getUrl().replace(parent.getUrl(), ""));
                        }
                    }
                    if (bean.getName() != null && bean.getName().startsWith("/") && !"/system-turn".equals(bean.getName())
                            && !"/system-disaster".equals(bean.getName()) && !"/system-partition".equals(bean.getName())
                            && !"/system-pod".equals(bean.getName())) {
                        bean.setName(bean.getName().substring(1));
                    }
                    if(m.isMenu()){
                        bean.setOpenNewWindow(m.getOpenNewWindow()== null ? 0 :m.getOpenNewWindow());
                    }
                } else if (m.isButton()) {
                    AuthorityOperationBean bean = convert2Operation(m);
                    AuthorityBean parent = createPath(getSafeParent(m), beanIdMap, top);
                    if (parent != null) {
                        parent.addOperation(bean);
                    }
                }
            } catch (Exception e) {
                log.error("菜单解析出现异常： " + e.getMessage(), e);
            }
        }
        // 按照ID排序顶部菜单，保持顺序不变，解决更改顶部菜单menuOrder后，乱序问题
        // 这是一种临时的解决办法，根源在于前端的子系统顺序是写死的，同时按照序号识别系统，没有按照名称
        sortTopMenusById(top);
        sortAllChildrenMenus(top);
        // 过滤菜单集合下面没有菜单的项
        this.removeEmptyChildrenTopMenu(top);
        return top;
    }

    private void removeEmptyChildrenTopMenu(List<AuthorityBean> topAuthorityBeanList) {
        if (CollectionUtils.isEmpty(topAuthorityBeanList)) {
            return;
        }
        topAuthorityBeanList.removeIf(authorityBean -> authorityBean.getType() == 1 && CollectionUtils.isEmpty(authorityBean.getChildren()));
        if (CollectionUtils.isEmpty(topAuthorityBeanList)) {
            return;
        }
        for (AuthorityBean authorityBean : topAuthorityBeanList) {
            if (authorityBean.getType() != 1) {
                continue;
            }
            List<AuthorityBean> children = authorityBean.getChildren();
            this.removeEmptyChildrenTopMenu(children);
        }
        topAuthorityBeanList.removeIf(authorityBean -> authorityBean.getType() == 1 && CollectionUtils.isEmpty(authorityBean.getChildren()));
    }

    private void sortTopMenusById(List<AuthorityBean> top) {
        if (top.size() == 0) {
            return;
        }
        Collections.sort(top, new Comparator<AuthorityBean>() {

            @Override
            public int compare(AuthorityBean o1, AuthorityBean o2) {
                return (int) (o1.getOrder() - o2.getOrder());
            }
        });
    }

    private void sortAllChildrenMenus(List<AuthorityBean> top) {
        if (top.size() == 0) {
            return;
        }
        List<AuthorityBean> stack = new ArrayList<>();
        for (AuthorityBean b : top) {
            // 初始化种子节点
            if (b.getChildren() != null && b.getChildren().size() > 0) {
                stack.add(b);
            }
        }
        while (stack.size() > 0) {
            AuthorityBean first = stack.remove(0);
            sortMenu(first.getChildren());
            for (AuthorityBean b : first.getChildren()) {
                // 遍历子节点
                if (b.getChildren() != null && b.getChildren().size() > 0) {
                    stack.add(b);
                }
            }
        }
    }

    private void sortMenu(List<AuthorityBean> top) {
        if (top.size() > 0) {
            Collections.sort(top, new Comparator<AuthorityBean>() {

                @Override
                public int compare(AuthorityBean o1, AuthorityBean o2) {
                    return o1.getOrder() - o2.getOrder();
                }
            });
        }
    }

    private AuthorityBean convert2Menu(BaseMenuFunction m, List<AuthorityBean> top) {
        AuthorityBean b = convert2Menu(m);
        if (m.getDepth() != null && m.getDepth() == 1) {
            top.add(b);
        }
        return b;
    }

    private AuthorityBean convert2Menu(BaseMenuFunction m) {
        AuthorityBean b = new AuthorityBean();
        b.setIcon(m.getIcon());
        b.setId(m.getId());
        b.setLabel(m.getName());
        b.setName(m.getUrl());
        b.setUrl(m.getUrl());
        b.setWorkFlowId(m.getWorkFlowId());
        b.setDashboardIcon(m.getDashboardIcon());
        b.setInquiryId(m.getInquiryId());
        b.setModelId(m.getModelId());

        if (m.isButton()) {
            b.setType(3);
        } else if (m.isFolder()) {
            b.setType(1);
        } else if (m.isMenu()) {
            b.setType(2);
            b.setOpenNewWindow(m.getOpenNewWindow()== null ? 0 :m.getOpenNewWindow());
        }
        b.setOrder(m.getMenuOrder());
        return b;
    }

    private AuthorityBean createPath(BaseMenuFunction parent, Map<Long, AuthorityBean> beanIdMap,
                                     List<AuthorityBean> top) {
        if (parent == null) {
            return null;
        }
        if (parent.isFolder() || parent.isMenu()) {
            AuthorityBean menu = beanIdMap.get(parent.getId());
            if (menu == null) {
                menu = convert2Menu(parent, top);
                beanIdMap.put(parent.getId(), menu);
            }
            AuthorityBean first = menu;
            while ((parent = getSafeParent(parent)) != null) {
                AuthorityBean parentMenu = beanIdMap.get(parent.getId());
                if (parentMenu == null) {
                    parentMenu = convert2Menu(parent, top);
                    beanIdMap.put(parent.getId(), parentMenu);
                }
                menu.setName(menu.getUrl());
                if (menu.getUrl() != null && parentMenu.getUrl() != null) {
                    menu.setName(menu.getUrl().replace(parentMenu.getUrl(), ""));
                }
                if (menu.getName() != null && menu.getName().startsWith("/") && !"/system-turn".equals(menu.getName())
                        && !"/system-disaster".equals(menu.getName()) && !"/system-partition".equals(menu.getName())
                        && !"/system-pod".equals(menu.getName())) {
                    menu.setName(menu.getName().substring(1));
                }

                parentMenu.addChild(menu);
                menu = parentMenu;
            }
            return first;
        }
        return null;
    }

    private BaseMenuFunction getSafeParent(BaseMenuFunction m) {
        try {
            if (m.getParent() == null || m.getParent().getName() == null || (m.getParent().getShowState() != null && m.getParent().getShowState() == 0)) {
                return null;
            }
        } catch (Exception e) {
            log.debug("parent menu not found, will ignore the menu.");
            return null;
        }
        return m.getParent();
    }

    private AuthorityOperationBean convert2Operation(BaseMenuFunction m) {
        AuthorityOperationBean bean = new AuthorityOperationBean();
        bean.setId(m.getId());
        bean.setName(m.getUrl());
        bean.setPerm(m.getPerm());
        bean.setLabel(m.getName());
        return bean;
    }

    private List<BaseMenuFunction> queryForUserAuthorities(Long jobId, Long userId) {
        // userMenuFunctionDao
        List<Long> ids = userMenuFunctionDao.selectMenuIdsByUserId(userId);
        if (ids == null || ids.isEmpty()) {
            if (jobId == null) {
                BaseUser user = userDao.getOne(userId);
                jobId = user.getJob();
                if (jobId == null) {
                    return Collections.EMPTY_LIST;
                }
            }
            BpJob one = jobDao.getOne(jobId);
            return new ArrayList<>(one.getBaseMenuFunctions());
        }

        List<BaseMenuFunction> functions = menuFunctionDao.selectListById(ids);
        return functions;
    }

    private List<BaseMenuFunction> queryForRoleAuthorities(Long roleId) {
        // userMenuFunctionDao
        List<Long> ids = roleMenuFunctionDao.selectMenuIdsByJobId(roleId);
        if (ids.isEmpty()) {
            return Collections.EMPTY_LIST;
        }
        List<BaseMenuFunction> functions = menuFunctionDao.selectListById(ids);
        return functions;
    }

    @Override
    @Transactional
    public List<AuthorityBean> queryAuthorityByUserId(Long userId, boolean superAdmin) {
        List<BaseMenuFunction> list = queryMenuFunctionByUserId(userId, superAdmin);
        if (!list.isEmpty()) {
            return parse(list);
        }
        return Collections.EMPTY_LIST;
    }

    @Override
    public List<BaseMenuFunction> queryMenuFunctionByUserId(Long userId, boolean superAdmin) {
        if (superAdmin) {
            // 超级管理员，返回所有权限
            List<BaseMenuFunction> all = menuFunctionDao.findAllByShowState();
            //
            licenceService.filter(all);
            return all;
        }
        List<Long> roleIds = baseRoleUserLoginRoleDao.selectRoleIdsByUserId(userId);
        if (roleIds.size() > 0) {
            List<Long> menuIds = roleMenuFunctionDao.selectMenuIdsByRoleIds(roleIds);
            if (menuIds.size() > 0) {
                List<BaseMenuFunction> menus = menuFunctionDao.findByIdsAndShowState(menuIds);
                licenceService.filter(menus);
                return menus;
            }
        }
        return Collections.EMPTY_LIST;
    }

    @Override
    public List<BaseMenuFunction> findAppMenuList(Long userId, boolean superAdmin) {
        List<String> types = new ArrayList<>();
        types.add(MenuTypes.MENU.getCode());
        types.add(MenuTypes.FOLDER.getCode());
        // 超级管理员，返回所有权限
        if (superAdmin) {
            List<BaseMenuFunction> menus = menuFunctionDao.findAppMenuByParamForAdmin(types, Constants.APP_MENU);
            licenceService.filter(menus);
            return menus;
        } else {
            List<Long> roleIds = baseRoleUserLoginRoleDao.selectRoleIdsByUserId(userId);
            if (CollectionUtils.isNotEmpty(roleIds)) {
                List<Long> menuIds = roleMenuFunctionDao.selectMenuIdsByRoleIds(roleIds);
                if (CollectionUtils.isNotEmpty(menuIds)) {
                    List<BaseMenuFunction> menus = menuFunctionDao.findAppMenuByParam(menuIds, types, Constants.APP_MENU);
                    licenceService.filter(menus);
                    return menus;
                }
            }
        }
        return null;
    }

    @Override
    public List<ShiroUser> kickOutUser(java.util.function.Predicate<ShiroUser> predicate) {
        SessionDAO sessionDAO = defaultSessionManager.getSessionDAO();
        Collection<Session> activeSessions = sessionDAO.getActiveSessions();
        Iterator<Session> sessionIterator = activeSessions.iterator();
        List<ShiroUser> kickOutUserList = new ArrayList<>();
        while (sessionIterator.hasNext()) {
            Session activeSession = sessionIterator.next();
            Object userObject = activeSession.getAttribute("user");
            if (userObject == null) {
                continue;
            }
            ShiroUser user = (ShiroUser) userObject;
            if (predicate.test(user)) {
                sessionDAO.delete(activeSession);
                kickOutUserList.add(user);
            }
        }
        return kickOutUserList;
    }

    @Override
    public List<SimpleSelectListBean> queryMenuListByUserId(Long userId, boolean superAdmin) {
        List<BaseMenuFunction> list = queryMenuFunctionByUserId(userId, superAdmin);
        if (!list.isEmpty()) {
            return list.stream().map(e -> {
                SimpleSelectListBean bean = new SimpleSelectListBean();
                bean.setLabel(e.getName());
                bean.setValue(e.getId());
                return bean;
            }).collect(Collectors.toList());
        }
        return Collections.EMPTY_LIST;
    }

    @Transactional
    @Override
    public List<AuthorityBean> queryForEditByRoleId(Long roleId) {
        List<BaseMenuFunction> all = menuFunctionDao.findAllByShowState();
        licenceService.filter(all);

        List<BaseMenuFunction> userAuthorities = queryForRoleAuthorities(roleId);
        licenceService.filter(userAuthorities);

        List<AuthorityBean> parse = parse(all);
        for (AuthorityBean b : parse) {
            markSelected(b, userAuthorities);
        }
        return parse;
    }

    /**
     * 根据角色列表查询系统名称列表 （depth=1)
     *
     * @return
     */
    @Override
    public List<SimpleSelectListBean> selectSystemList() {
        List<BaseMenuFunction> systemList = menuFunctionDao.findByDepth(1);
        if (systemList == null) {
            return Collections.EMPTY_LIST;
        }
        List<SimpleSelectListBean> list = new ArrayList<>();
        for (BaseMenuFunction m : systemList) {
            SimpleSelectListBean b = new SimpleSelectListBean();
            b.setValue(m.getId());
            b.setLabel(m.getName());
            list.add(b);
        }
        return list;
    }

    private void markSelected(AuthorityBean filtered, List<BaseMenuFunction> userAuthorities) {
        Map<Long, BaseMenuFunction> idMap = new HashMap<>();
        for (BaseMenuFunction b : userAuthorities) {
            idMap.put(b.getId(), b);
        }
        List<AuthorityBean> all = new ArrayList<>();
        all.add(filtered);
        while (all.size() > 0) {
            // 采用非递归方式遍历所有的子节点
            AuthorityBean now = all.get(0);
            if (idMap.containsKey(now.getId())) {
                now.setSelected(true);
            }
            if (now.getAuth() != null) {
                for (AuthorityOperationBean ao : now.getAuth()) {
                    if (idMap.containsKey(ao.getId())) {
                        ao.setSelected(true);
                    }
                }
            }
            if (now.getChildren() != null) {
                all.addAll(now.getChildren());
            }
            all.remove(0);
        }
    }

    @Override
    @Transactional
    public List<AuthorityBean> queryForTopMenu() {
        List<BaseMenuFunction> menus = menuFunctionDao.findByDepth(1);
        List<AuthorityBean> list = new ArrayList<>(menus.size());
        for (BaseMenuFunction m : menus) {
            list.add(convert2Menu(m));
        }
        return list;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Pair<Set<String>, Set<String>> queryUserPerms(Long userId) {
        Assert.notNull(userId, "userId不能为空");
        List<Long> roleIds = baseRoleUserLoginRoleDao.selectRoleIdsByUserId(userId);
        if (roleIds.size() > 0) {
            Set<String> roleSet = roleDao.findAllById(roleIds).stream().map(r -> r.getName()).collect(Collectors.toSet());
            List<Long> menuIds = roleMenuFunctionDao.selectMenuIdsByRoleIds(roleIds);
            if (menuIds.size() > 0) {
                List<BaseMenuFunction> menus = menuFunctionDao.findAllById(menuIds);
                Set<String> re = new HashSet<>(menus.size());
                for (BaseMenuFunction f : menus) {
                    if (StringUtils.isNotBlank(f.getPerm())) {
                        re.add(f.getPerm().trim());
                    }
                }
                return new Pair<>(re, roleSet);
            }
            return new Pair<>(Collections.EMPTY_SET, roleSet);
        }
        return new Pair<>(Collections.EMPTY_SET, Collections.EMPTY_SET);
    }

    @Override
    public void updateAuthority(Long jobId, Long userId, List<AuthorityBean> list) {
        if (userId != null) {
            updateUserAuthority(userId, list);
        } else if (jobId != null) {
            updateRoleAuthority(jobId, list);
        }
    }

    @Transactional
    protected void updateRoleAuthority(Long jobId, List<AuthorityBean> list) {
        List<Long> authorites = findSelectedAuthorites(list);
        System.out.println("更新角色权限:" + jobId);
        System.out.println("新赋值所有权限:" + authorites);
        List<Long> existsAuthories = roleMenuFunctionDao.selectMenuIdsByJobId(jobId);
        System.out.println("已有权限:" + existsAuthories);
        List<Long> keepList = new ArrayList<>(authorites);
        keepList.retainAll(existsAuthories);
        System.out.println("需保留权限:" + keepList);

        // 需删除的权限
        existsAuthories.removeAll(keepList);
        if (existsAuthories.size() > 0) {
            roleMenuFunctionDao.deleteByIds(jobId, existsAuthories);
        }
        System.out.println("需删除权限:" + existsAuthories);

        // 需新增的权限
        authorites.removeAll(keepList);
        System.out.println("新增权限:" + authorites);
        batchAddRoleMenuFunction(jobId, authorites);
    }

    private void batchAddRoleMenuFunction(Long jobId, List<Long> authorites) {
        if (authorites.isEmpty()) {
            return;
        }
        List<BaseRoleMenuFunction> all = new ArrayList<>(authorites.size());
        for (Long menuId : authorites) {
            BaseRoleMenuFunction function = new BaseRoleMenuFunction();
            function.setRoleId(jobId);
            function.setMenuId(menuId);
            all.add(function);
        }
        roleMenuFunctionDao.saveAll(all);
    }

    @Transactional
    public void updateUserAuthority(Long userId, List<AuthorityBean> list) {
        List<Long> authorites = findSelectedAuthorites(list);
        List<Long> existsAuthories = userMenuFunctionDao.selectMenuIdsByUserId(userId);
        System.out.println("更新岗位权限:" + userId);
        System.out.println("新赋值所有权限:" + authorites);
        List<Long> keepList = new ArrayList<>(authorites);
        keepList.retainAll(existsAuthories);

        // 需删除的权限
        existsAuthories.removeAll(keepList);
        System.out.println("需删除的权限:" + existsAuthories);
        if (existsAuthories.size() > 0) {
            userMenuFunctionDao.deleteByIds(userId, existsAuthories);
        }

        // 需新增的权限
        authorites.removeAll(keepList);
        System.out.println("新增加的权限:" + authorites);
        batchAddUserMenuFunction(userId, authorites);
    }

    private void batchAddUserMenuFunction(Long userId, List<Long> authorites) {
        if (authorites.isEmpty()) {
            return;
        }
        List<BaseUserMenuFunction> all = new ArrayList<>(authorites.size());
        for (Long menuId : authorites) {
            BaseUserMenuFunction function = new BaseUserMenuFunction();
            function.setUserId(userId);
            function.setMenuId(menuId);
            all.add(function);
        }
        userMenuFunctionDao.saveAll(all);
    }

    List<Long> findSelectedAuthorites(List<AuthorityBean> list) {
        List<AuthorityBean> all = new ArrayList<>();
        List<Long> result = new ArrayList<>();
        all.addAll(list);
        while (all.size() > 0) {
            // 采用非递归方式遍历所有的子节点
            AuthorityBean now = all.get(0);
            if (now.getChildren() != null) {
                all.addAll(now.getChildren());
            }
            if (now.getSelected() != null && now.getSelected() == true) {
                result.add(now.getId());
            }
            // 添加按钮权限
            if (now.getAuth() != null && now.getAuth().size() > 0) {
                for (AuthorityOperationBean ao : now.getAuth()) {
                    if (ao.isSelected()) {
                        result.add(ao.getId());
                    }
                }
            }
            all.remove(0);
        }
        return result;
    }

    @Override
    public void addOrUpdateMenu(BaseMenuFunctionEditBean bean) {
        BaseMenuFunction function = null;
        if (bean.getId() != null) {
            function = menuFunctionDao.getOne(bean.getId());
            Assert.isTrue(Objects.equals(bean.getType(), function.getType()), "不能更改菜单的类型");
            function.setName(bean.getName());
            function.setIcon(bean.getIcon());
            function.setMenuOrder(bean.getMenuOrder() == null ? 100 : bean.getMenuOrder());
            setParentAndLevel(bean, function);
            function.setPerm(bean.getPerm());
            function.setUrl(bean.getUrl());
        } else {
            function = new BaseMenuFunction();
            function.setName(bean.getName());
            function.setIcon(bean.getIcon());
            function.setMenuOrder(bean.getMenuOrder() == null ? 100 : bean.getMenuOrder());
            setParentAndLevel(bean, function);
            function.setType(bean.getType());
            function.setPerm(bean.getPerm());
            function.setUrl(bean.getUrl());
        }
        menuFunctionDao.save(function);
    }

    private void setParentAndLevel(BaseMenuFunctionEditBean bean, BaseMenuFunction function) {
        if (bean.getParentId() != null) {
            BaseMenuFunction parent = menuFunctionDao.getOne(bean.getParentId());
            boolean illegalRelation = parent.isFolder() && "menu".equals(bean.getType())
                    || parent.isMenu() && "button".equals(bean.getType());
            Assert.isTrue(illegalRelation, "集合可以添加菜单，菜单可以添加按钮。请检查是否父类型是否正确");
            function.setParent(parent);
            function.setDepth(parent.getDepth() + 1);
        } else {
            function.setParent(null);
            function.setDepth(1);
        }
    }

    @Override
    public List<BaseMenuFunctionEditBean> queryMenuByName(String name, boolean exactMatch) {
        QBaseMenuFunction q = QBaseMenuFunction.baseMenuFunction;
        Predicate condition = null;
        if (exactMatch) {
            condition = q.name.eq(name);
        } else {
            condition = q.name.like("%" + name + "%");
        }
        Iterable<BaseMenuFunction> all = menuFunctionDao.findAll(condition);
        List<BaseMenuFunctionEditBean> list = new ArrayList<>();
        for (BaseMenuFunction b : all) {
            BaseMenuFunctionEditBean mb = new BaseMenuFunctionEditBean();
            BeanUtils.copyProperties(b, mb);
            if (b.getParent() != null) {
                mb.setParentId(b.getParent().getId());
            }
            list.add(mb);
        }
        return list;
    }

    @Override
    public List<SimpleSelectListBean> queryForUserRoleList(Long userId) {
        List<Long> roleIds = baseRoleUserLoginRoleDao.selectRoleIdsByUserId(userId);
        if (roleIds.isEmpty()) {
            return Collections.EMPTY_LIST;
        }
        List<BaseRole> roles = roleDao.findAllById(roleIds);
        return roles.stream().map(e -> {
            SimpleSelectListBean b = new SimpleSelectListBean();
            b.setLabel(e.getName());
            b.setValue(e.getId());
            return b;
        }).collect(Collectors.toList());
    }

    @Override
    @Transactional
    public void updateUserRoles(UserAssignRoleBean bean) {
        baseRoleUserLoginRoleDao.deleteByUserId(bean.getUserId());
        if (bean.getRoleIds() != null && bean.getRoleIds().length > 0) {
            List<BaseRoleUserLoginRole> roles = new ArrayList<>(bean.getRoleIds().length);
            for (Long rid : bean.getRoleIds()) {
                BaseRoleUserLoginRole b = new BaseRoleUserLoginRole();
                b.setUserId(bean.getUserId());
                b.setRoleId(rid);
                roles.add(b);
            }
            baseRoleUserLoginRoleDao.saveAll(roles);
        }
    }

    @Override
    public List<DashboardMenuBean> queryDashboardList() {
        List<AuthorityBean> authList = queryAuthorityByUserId(Context.getCurrentUserId(),
                Context.getCurrentUser().isSuperAdmin());
        return convertMenuData(authList);
    }

    @Override
    public List<DashboardMenuBean> convertMenuData(List<AuthorityBean> authList) {
        List<DashboardMenuBean> list = new ArrayList<>();
        for (AuthorityBean au : authList) {
            DashboardMenuBean dashboard = new DashboardMenuBean();
            dashboard.setLabel(au.getLabel());
            List<DashboardMenuDetailBean> details = new ArrayList<>();
            List<AuthorityBean> authorityBeans = au.getChildren();
            if (authorityBeans != null) {
                this.convertMenuData(details, authorityBeans);
            }
            dashboard.setMenuList(details);
            list.add(dashboard);
        }
        return list;
    }

    /**
     * 递归过滤查找多层级菜单集合
     *
     * @param detailBeanList
     * @param authorityBeanList
     */
    private void convertMenuData(List<DashboardMenuDetailBean> detailBeanList, List<AuthorityBean> authorityBeanList) {
        if (CollectionUtils.isEmpty(authorityBeanList)) {
            return;
        }
        for (AuthorityBean b : authorityBeanList) {
            if (StringUtils.isNotEmpty(b.getDashboardIcon()) && b.getType() == 2) {
                detailBeanList.add(convertBean(b));
            }
            List<AuthorityBean> children = b.getChildren();
            convertMenuData(detailBeanList, children);
        }
    }

    @Override
    @Transactional
    public void roleUpdateUsers(BaseRoleAddUserBean bean) {

        if (bean.getRoleId() != null) {
            baseRoleUserLoginRoleDao.deleteByRoleId(bean.getRoleId());
        }
        List<Long> userIds = bean.getUserIds();
        if (userIds != null && !userIds.isEmpty()) {
            List<BaseRoleUserLoginRole> roles = new ArrayList<>();
            for (Long uid : userIds) {
                BaseRoleUserLoginRole b = new BaseRoleUserLoginRole();
                b.setUserId(uid);
                b.setRoleId(bean.getRoleId());
                roles.add(b);
            }
            baseRoleUserLoginRoleDao.saveAll(roles);
        }
    }

    @Override
    public ResultBean roleUserList(BaseUserRoleListSearchBean bean) {
        Integer totalCount = userDao.findRoleUserListCount(bean.getNameOrCode(), bean.getDepartId(), bean.getJobId(), bean.getRoleId());
        if (totalCount == null) {
            return ResultBean.pageData(new ArrayList(), 0);
        }
        Integer page = bean.getPage() == null ? 0 : bean.getPage();
        Integer pageSize = bean.getSize() == null ? 15 : bean.getSize();
        List<Map<String, Object>> resList = userDao.findRoleUserList((page) * pageSize, pageSize, bean.getNameOrCode(), bean.getDepartId(), bean.getJobId(), bean.getRoleId());
        List<BaseRoleUserListBean> list = new ArrayList<>();
        if (resList != null) {
            for (Map<String, Object> map : resList) {
                BaseRoleUserListBean user = new BaseRoleUserListBean();
                user.setId(new Long(map.get("id").toString()));
                user.setCode(map.get("code") == null ? "" : map.get("code").toString());
                user.setRealName(map.get("realName") == null ? "" : map.get("realName").toString());
                user.setDepartName(map.get("departName") == null ? "" : map.get("departName").toString());
                user.setJobName(map.get("jobName") == null ? "" : map.get("jobName").toString());
                user.setHasRole(map.get("roleId") == null ? false : true);
                list.add(user);
            }
        }
        return ResultBean.pageData(list, totalCount);
    }

    @Override
    public ResultBean newRoleUserList(BaseUserRoleListSearchBean bean) {
        List<Long> list = userDao.findNewRoleUserList(bean.getNameOrCode(), bean.getDepartId(), bean.getJobId());
        return ResultBean.success(list);
    }

    @Override
    public ResultBean roleUserListAll(Long roleId) {
        List<Long> userIdList = userDao.findRoleUserListAll(roleId);
        return ResultBean.success(userIdList);
    }


    private DashboardMenuDetailBean convertBean(AuthorityBean b) {
        DashboardMenuDetailBean detail = new DashboardMenuDetailBean();
        detail.setId(b.getId());
        detail.setUrl(b.getUrl());
        detail.setDialog(true);
        detail.setIcon(b.getDashboardIcon());
        detail.setLabel(b.getLabel());
        return detail;
    }


}
